home *** CD-ROM | disk | FTP | other *** search
- /*
- * SAM.c - Simple Assembler and Monitor With Integrated System Explorer
- *
- * Copyright (C) 1994-1995 by Christian Bauer
- */
-
- #include <exec/types.h>
- #include <clib/dos_protos.h>
- #include <clib/utility_protos.h>
-
- #include "SAM.h"
- #include "6526.h"
- #include "6581.h"
- #include "6569.h"
-
-
- // Aus 6510.asm
- extern UBYTE RA, RX, RY, RP, RPR, RDDR;
- extern UWORD RPC, RS;
- extern UBYTE SAMReadByte(UWORD address);
- extern void SAMWriteByte(UWORD address, UBYTE byte);
- extern UBYTE SAMMemConfig;
-
-
- // Prototypes
- void error(char *s); // Scanner
- BOOL aborted(void);
- void read_line(void);
- char get_char(void);
- void put_back(char c);
- enum Token get_token(void);
- UWORD get_number(void);
-
- BOOL expression(UWORD *number); // Parser
- BOOL term(UWORD *number);
- BOOL factor(UWORD *number);
- BOOL address_args(void);
- BOOL range_args(int def_range);
- BOOL instr_args(UWORD *number, char *mode);
-
- void help(void); // Routinen für die Befehle
- void display_registers(void);
- void memory_dump(void);
- void ascii_dump(void);
- char conv_from_64(char c);
- void screen_dump(void);
- char conv_from_scode(char c);
- void binary_dump(void);
- void sprite_dump(void);
- void byte_to_bin(UBYTE byte, char *str);
- void disassemble(void);
- int disass_line(UWORD adr, UBYTE op, UBYTE lo, UBYTE hi);
- void assemble(void);
- char find_mnemonic(char op1, char op2, char op3);
- BOOL find_opcode(char mnem, char mode, UBYTE *opcode);
- void mem_config(void);
- void fill(void);
- void compare(void);
- void transfer(void);
- void modify(void);
- void print_expr(void);
- void redir_output(void);
- void int_vectors(void);
- void view_state(void);
- void view_cia_state(void);
- void dump_cia_ints(UBYTE int);
- void view_sid_state(void);
- void dump_sid_waveform(UBYTE wave);
- void view_vic_state(void);
- void dump_spr_flags(UBYTE f);
- void dump_vic_ints(UBYTE int);
-
-
- // FileHandles für Eingabe, Ausgabe und Fehler
- BPTR fin, fout, ferr;
-
- // Eingabezeile
- #define INPUT_LENGTH 80
- char input[INPUT_LENGTH];
- char *in_ptr;
-
- UWORD address, end_address;
-
- // Eingabetoken
- enum Token {
- T_NULL, // Ungültiges Token
- T_END, // Ende der Zeile
- T_NUMBER, // Hexadezimalzahl
- T_LPAREN, // '('
- T_RPAREN, // ')'
- T_ADD, // '+'
- T_SUB, // '-'
- T_MUL, // '*'
- T_DIV, // '/'
- T_COMMA, // ','
- T_IMMED, // '#'
- T_X, // 'x'
- T_Y, // 'y'
- T_PC, // 'pc'
- T_SP // 'sp'
- };
-
- enum Token the_token;
- UWORD the_number; // Enthält die Zahl, wenn the_token==T_NUMBER
-
- // Adressierungsarten
- enum {
- A_IMPL,
- A_ACCU, // A
- A_IMM, // #zz
- A_REL, // Branches
- A_ZERO, // zz
- A_ZEROX, // zz,x
- A_ZEROY, // zz,y
- A_ABS, // zzzz
- A_ABSX, // zzzz,x
- A_ABSY, // zzzz,y
- A_IND, // (zzzz)
- A_INDX, // (zz,x)
- A_INDY // (zz),y
- };
-
- // Mnemonics
- enum {
- M_ADC, M_AND, M_ASL, M_BCC, M_BCS, M_BEQ, M_BIT, M_BMI, M_BNE, M_BPL,
- M_BRK, M_BVC, M_BVS, M_CLC, M_CLD, M_CLI, M_CLV, M_CMP, M_CPX, M_CPY,
- M_DEC, M_DEX, M_DEY, M_EOR, M_INC, M_INX, M_INY, M_JMP, M_JSR, M_LDA,
- M_LDX, M_LDY, M_LSR, M_NOP, M_ORA, M_PHA, M_PHP, M_PLA, M_PLP, M_ROL,
- M_ROR, M_RTI, M_RTS, M_SBC, M_SEC, M_SED, M_SEI, M_STA, M_STX, M_STY,
- M_TAX, M_TAY, M_TSX, M_TXA, M_TXS, M_TYA,
-
- M_ILLEGAL, // Ab hier kommen die undokumentierten Opcodes
-
- M_IANC, M_IANE, M_IARR, M_IASR, M_IDCP, M_IISB, M_IJAM, M_INOP, M_ILAS,
- M_ILAX, M_ILXA, M_IRLA, M_IRRA, M_ISAX, M_ISBC, M_ISBX, M_ISHA, M_ISHS,
- M_ISHX, M_ISHY, M_ISLO, M_ISRE,
-
- M_MAXIMUM // Höchstes Element
- };
-
- // Zu jedem Opcode das Mnemonic
- const char mnemonic[256] = {
- M_BRK , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, // 00
- M_PHP , M_ORA , M_ASL , M_IANC, M_INOP, M_ORA, M_ASL , M_ISLO,
- M_BPL , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, // 10
- M_CLC , M_ORA , M_INOP, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO,
- M_JSR , M_AND , M_IJAM, M_IRLA, M_BIT , M_AND, M_ROL , M_IRLA, // 20
- M_PLP , M_AND , M_ROL , M_IANC, M_BIT , M_AND, M_ROL , M_IRLA,
- M_BMI , M_AND , M_IJAM, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA, // 30
- M_SEC , M_AND , M_INOP, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA,
- M_RTI , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, // 40
- M_PHA , M_EOR , M_LSR , M_IASR, M_JMP , M_EOR, M_LSR , M_ISRE,
- M_BVC , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, // 50
- M_CLI , M_EOR , M_INOP, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE,
- M_RTS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, // 60
- M_PLA , M_ADC , M_ROR , M_IARR, M_JMP , M_ADC, M_ROR , M_IRRA,
- M_BVS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, // 70
- M_SEI , M_ADC , M_INOP, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA,
- M_INOP, M_STA , M_INOP, M_ISAX, M_STY , M_STA, M_STX , M_ISAX, // 80
- M_DEY , M_INOP, M_TXA , M_IANE, M_STY , M_STA, M_STX , M_ISAX,
- M_BCC , M_STA , M_IJAM, M_ISHA, M_STY , M_STA, M_STX , M_ISAX, // 90
- M_TYA , M_STA , M_TXS , M_ISHS, M_ISHY, M_STA, M_ISHX, M_ISHA,
- M_LDY , M_LDA , M_LDX , M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX, // a0
- M_TAY , M_LDA , M_TAX , M_ILXA, M_LDY , M_LDA, M_LDX , M_ILAX,
- M_BCS , M_LDA , M_IJAM, M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX, // b0
- M_CLV , M_LDA , M_TSX , M_ILAS, M_LDY , M_LDA, M_LDX , M_ILAX,
- M_CPY , M_CMP , M_INOP, M_IDCP, M_CPY , M_CMP, M_DEC , M_IDCP, // c0
- M_INY , M_CMP , M_DEX , M_ISBX, M_CPY , M_CMP, M_DEC , M_IDCP,
- M_BNE , M_CMP , M_IJAM, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP, // d0
- M_CLD , M_CMP , M_INOP, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP,
- M_CPX , M_SBC , M_INOP, M_IISB, M_CPX , M_SBC, M_INC , M_IISB, // e0
- M_INX , M_SBC , M_NOP , M_ISBC, M_CPX , M_SBC, M_INC , M_IISB,
- M_BEQ , M_SBC , M_IJAM, M_IISB, M_INOP, M_SBC, M_INC , M_IISB, // f0
- M_SED , M_SBC , M_INOP, M_IISB, M_INOP, M_SBC, M_INC , M_IISB
- };
-
- // Zu jedem Opcode die Adressierungsart
- const char adr_mode[256] = {
- A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 00
- A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 10
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
- A_ABS , A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 20
- A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 30
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
- A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 40
- A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 50
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
- A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 60
- A_IMPL, A_IMM , A_ACCU, A_IMM , A_IND , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 70
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
- A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 80
- A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY, // 90
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY,
- A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // a0
- A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY, // b0
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY,
- A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // c0
- A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // d0
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX,
- A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // e0
- A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS,
- A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // f0
- A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX
- };
-
- // Zu jedem Mnemonic die Zeichen
- const char mnem_1[] = "aaabbbbbbbbbbcccccccdddeiiijjllllnopppprrrrssssssstttttt?aaaadijnlllrrsssssssss";
- const char mnem_2[] = "dnscceimnprvvllllmppeeeonnnmsdddsorhhlloottbeeetttaasxxy?nnrscsaoaaxlrabbhhhhlr";
- const char mnem_3[] = "cdlcsqtielkcscdivpxycxyrcxypraxyrpaapaplrisccdiaxyxyxasa?cerrpbmpsxaaaxcxasxyoe";
-
- // Zu jeder Adressierungsart die Befehlslänge
- const char adr_length[] = {1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2};
-
-
- /*
- * SAM öffnen und handhaben
- */
-
- void SAM(void)
- {
- BOOL done = FALSE;
- char c;
-
- if (fin = fout = ferr = Open("CON:0/0/640/480/SAM", MODE_NEWFILE)) {
- FPuts(ferr, "\n *** SAM - Simple Assembler and Monitor ***\n *** Press 'h' for help ***\n\n");
- display_registers();
-
- address = RPC;
-
- while (!done) {
- Write(ferr, "> ", 2);
- read_line();
- while ((c = get_char()) == ' ') ;
-
- switch (c) {
- case 'a': // Assemblieren
- get_token();
- assemble();
- break;
-
- case 'b': // Binär-Dump
- get_token();
- binary_dump();
- break;
-
- case 'c': // Vergleichen
- get_token();
- compare();
- break;
-
- case 'd': // Disassemblieren
- get_token();
- disassemble();
- break;
-
- case 'e': // Interrupt-Vektoren
- int_vectors();
- break;
-
- case 'f': // Füllen
- get_token();
- fill();
- break;
-
- case 'h': // Help
- help();
- break;
-
- case 'i': // ASCII-Dump
- get_token();
- ascii_dump();
- break;
-
- case 'k': // Speicherkonfiguration
- get_token();
- mem_config();
- break;
-
- case 'm': // Memory-Dump
- get_token();
- memory_dump();
- break;
-
- case 'n': // Screen-Code-Dump
- get_token();
- screen_dump();
- break;
-
- case 'o': // Ausgabe umleiten
- redir_output();
- break;
-
- case 'p': // Sprite-Dump
- get_token();
- sprite_dump();
- break;
-
- case 'r': // Register
- display_registers();
- break;
-
- case 't': // Transfer
- get_token();
- transfer();
- break;
-
- case 'v': // View machine state
- view_state();
- break;
-
- case 'x': // Exit
- done = TRUE;
- break;
-
- case ':': // Ändern
- get_token();
- modify();
- break;
-
- case '?': // Ausdruck berechnen
- get_token();
- print_expr();
- break;
-
- case '\n': // Leerzeile
- break;
-
- default: // Unbekannter Befehl
- error("Unknown command");
- break;
- }
- }
-
- Close(fin);
- if (fout != ferr)
- Close(fout);
- }
- }
-
-
- /*
- * Fehlermeldung ausgeben
- */
-
- void error(char *s)
- {
- FPrintf(ferr, "*** %s\n", s);
- }
-
-
- /*
- * CTRL-C gedrückt?
- */
-
- #include <dos/dos.h>
- #include <clib/exec_protos.h>
- BOOL aborted(void)
- {
- return SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
- }
-
-
- /*
- * Eine Zeile von der Tastatur lesen
- */
-
- void read_line(void)
- {
- FGets(fin, in_ptr = input, INPUT_LENGTH);
- }
-
-
- /*
- * Ein Zeichen aus der Eingabezeile lesen
- */
-
- char get_char(void)
- {
- return *in_ptr++;
- }
-
-
- /*
- * Zeichen in die Eingabezeile zurückpacken
- */
-
- void put_back(char c)
- {
- *(--in_ptr) = c;
- }
-
-
- /*
- * Scanner: Ein Token aus der Eingabezeile lesen
- */
-
- enum Token get_token(void)
- {
- char c;
-
- // Leerzeichen überspringen
- while ((c = get_char()) == ' ') ;
-
- switch (ToLower(c)) {
- case '\n':
- return the_token = T_END;
- case '(':
- return the_token = T_LPAREN;
- case ')':
- return the_token = T_RPAREN;
- case '+':
- return the_token = T_ADD;
- case '-':
- return the_token = T_SUB;
- case '*':
- return the_token = T_MUL;
- case '/':
- return the_token = T_DIV;
- case ',':
- return the_token = T_COMMA;
- case '#':
- return the_token = T_IMMED;
- case 'x':
- return the_token = T_X;
- case 'y':
- return the_token = T_Y;
- case 'p':
- if (ToLower(get_char()) == 'c')
- return the_token = T_PC;
- else {
- error("Unrecognized token");
- return the_token = T_NULL;
- }
- case 's':
- if (ToLower(get_char()) == 'p')
- return the_token = T_SP;
- else {
- error("Unrecognized token");
- return the_token = T_NULL;
- }
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- put_back(c);
- the_number = get_number();
- return the_token = T_NUMBER;
- default:
- error("Unrecognized token");
- return the_token = T_NULL;
- }
- }
-
- UWORD get_number(void)
- {
- char c;
- UWORD i = 0;
-
- while (((c = ToLower(get_char())) >= '0') && (c <= '9') || (c >= 'a') && (c <= 'f'))
- if (c < 'a')
- i = (i << 4) + (c - '0');
- else
- i = (i << 4) + (c - 'a' + 10);
-
- put_back(c);
- return i;
- }
-
-
- /*
- * expression = term {(ADD | SUB) term}
- * TRUE: OK, FALSE: Fehler
- */
-
- BOOL expression(UWORD *number)
- {
- UWORD accu, trm;
-
- if (!term(&accu))
- return FALSE;
-
- for (;;)
- switch (the_token) {
- case T_ADD:
- get_token();
- if (!term(&trm))
- return FALSE;
- accu += trm;
- break;
-
- case T_SUB:
- get_token();
- if (!term(&trm))
- return FALSE;
- accu -= trm;
- break;
-
- default:
- *number = accu;
- return TRUE;
- }
- }
-
-
- /*
- * term = factor {(MUL | DIV) factor}
- * TRUE: OK, FALSE: Fehler
- */
-
- BOOL term(UWORD *number)
- {
- UWORD accu, fact;
-
- if (!factor(&accu))
- return FALSE;
-
- for (;;)
- switch (the_token) {
- case T_MUL:
- get_token();
- if (!factor(&fact))
- return FALSE;
- accu *= fact;
- break;
-
- case T_DIV:
- get_token();
- if (!factor(&fact))
- return FALSE;
- if (fact == 0) {
- error("Division by 0");
- return FALSE;
- }
- accu /= fact;
- break;
-
- default:
- *number = accu;
- return TRUE;
- }
- }
-
-
- /*
- * factor = NUMBER | PC | SP | LPAREN expression RPAREN
- * TRUE: OK, FALSE: Fehler
- */
-
- BOOL factor(UWORD *number)
- {
- switch (the_token) {
- case T_NUMBER:
- *number = the_number;
- get_token();
- return TRUE;
-
- case T_PC:
- get_token();
- *number = RPC;
- return TRUE;
-
- case T_SP:
- get_token();
- *number = RS;
- return TRUE;
-
- case T_LPAREN:
- get_token();
- if (expression(number))
- if (the_token == T_RPAREN) {
- get_token();
- return TRUE;
- } else {
- error("Missing ')'");
- return FALSE;
- }
- else {
- error("Error in expression");
- return FALSE;
- }
-
- case T_END:
- error("Required argument missing");
- return FALSE;
-
- default:
- error("'pc', 'sp', '(' or number expected");
- return FALSE;
- }
- }
-
-
- /*
- * address_args = [expression] END
- *
- * Startadresse nach address lesen
- *
- * TRUE: OK, FALSE: Fehler
- */
-
- BOOL address_args(void)
- {
- if (the_token == T_END)
- return TRUE;
- else {
- if (!expression(&address))
- return FALSE;
- return the_token == T_END;
- }
- }
-
-
- /*
- * range_args = [expression] [[COMMA] expression] END
- *
- * Startadresse nach address, Endadresse nach end_address lesen
- *
- * TRUE: OK, FALSE: Fehler
- */
-
- BOOL range_args(int def_range)
- {
- end_address = address + def_range;
-
- if (the_token == T_END)
- return TRUE;
- else {
- if (!expression(&address))
- return FALSE;
- end_address = address + def_range;
- if (the_token == T_END)
- return TRUE;
- else {
- if (the_token == T_COMMA) get_token();
- if (!expression(&end_address))
- return FALSE;
- return the_token == T_END;
- }
- }
- }
-
-
- /*
- * instr_args = END
- * | IMMED NUMBER END
- * | NUMBER [COMMA (X | Y)] END
- * | LPAREN NUMBER (RPAREN [COMMA Y] | COMMA X RPAREN) END
- *
- * Argumente eines 6510-Befehls lesen, Adresse und Adressierungsart ermitteln
- *
- * TRUE: OK, FALSE: Fehler
- */
-
- BOOL instr_args(UWORD *number, char *mode)
- {
- switch (the_token) {
-
- case T_END:
- *mode = A_IMPL;
- return TRUE;
-
- case T_IMMED:
- get_token();
- if (the_token == T_NUMBER) {
- *number = the_number;
- *mode = A_IMM;
- get_token();
- return the_token == T_END;
- } else {
- error("Number expected");
- return FALSE;
- }
-
- case T_NUMBER:
- *number = the_number;
- get_token();
- switch (the_token) {
-
- case T_END:
- if (*number < 0x100)
- *mode = A_ZERO;
- else
- *mode = A_ABS;
- return TRUE;
-
- case T_COMMA:
- get_token();
- switch (the_token) {
-
- case T_X:
- get_token();
- if (*number < 0x100)
- *mode = A_ZEROX;
- else
- *mode = A_ABSX;
- return the_token == T_END;
-
- case T_Y:
- get_token();
- if (*number < 0x100)
- *mode = A_ZEROY;
- else
- *mode = A_ABSY;
- return the_token == T_END;
-
- default:
- error("Illegal index register");
- return FALSE;
- }
-
- default:
- return FALSE;
- }
-
- case T_LPAREN:
- get_token();
- if (the_token == T_NUMBER) {
- *number = the_number;
- get_token();
- switch (the_token) {
- case T_RPAREN:
- get_token();
- switch (the_token) {
-
- case T_END:
- *mode = A_IND;
- return TRUE;
-
- case T_COMMA:
- get_token();
- if (the_token == T_Y) {
- *mode = A_INDY;
- get_token();
- return the_token == T_END;
- } else {
- error("Only 'y' index register allowed");
- return FALSE;
- }
-
- default:
- error("Illegal characters after ')'");
- return FALSE;
- }
-
- case T_COMMA:
- get_token();
- if (the_token == T_X) {
- get_token();
- if (the_token == T_RPAREN) {
- *mode = A_INDX;
- get_token();
- return the_token == T_END;
- } else {
- error("')' expected");
- return FALSE;
- }
- } else {
- error("Only 'x' index register allowed");
- return FALSE;
- }
-
- default:
- error("')' or ',' expected");
- return FALSE;
- }
- } else {
- error("Number expected");
- return FALSE;
- }
-
- default:
- error("'(', '#' or number expected");
- return FALSE;
- }
- }
-
-
- /*
- * Hilfstext anzeigen
- * ?
- */
-
- void help(void)
- {
- FPuts(fout, "a [start] Assemble\n"
- "b [start] [end] Binary dump\n"
- "c start end dest Compare memory\n"
- "d [start] [end] Disassemble\n"
- "e Show interrupt vectors\n"
- "f start end byte Fill memory\n"
- "i [start] [end] ASCII/PETSCII dump\n"
- "k [config] Show/set memory configuration\n"
- "m [start] [end] Memory dump\n"
- "n [start] [end] Screen code dump\n"
- "o [file] Redirect output\n"
- "p [start] [end] Sprite dump\n"
- "r Show registers\n"
- "t start end dest Transfer memory\n"
- "vc1 View CIA 1 state\n"
- "vc2 View CIA 2 state\n"
- "vs View SID state\n"
- "vv View VIC state\n"
- "x Return to Frodo\n"
- ": addr {byte} Modify memory\n"
- "? expression Calculate expression\n");
- }
-
-
- /*
- * 6510-Register anzeigen
- * r
- */
-
- void display_registers(void)
- {
- FPuts(fout, " PC A X Y SP DR PR NVDIZC Instruction\n");
- FPrintf(fout, "%04lx %02lx %02lx %02lx %04lx %02lx %02lx %lc%lc%lc%lc%lc%lc ",
- RPC, RA, RX, RY, RS, RDDR, RPR,
- RP & 0x80 ? '1' : '0', RP & 0x40 ? '1' : '0', RP & 0x08 ? '1' : '0',
- RP & 0x04 ? '1' : '0', RP & 0x02 ? '1' : '0', RP & 0x01 ? '1' : '0');
- disass_line(RPC, SAMReadByte(RPC), SAMReadByte(RPC+1), SAMReadByte(RPC+2));
- }
-
-
- /*
- * Memory-Dump
- * m [start] [end]
- */
-
- #define MEMDUMP_BPL 16 // Bytes pro Zeile
-
- void memory_dump(void)
- {
- BOOL done = FALSE;
- short i;
- UBYTE mem[MEMDUMP_BPL + 2];
- UBYTE byte;
-
- mem[MEMDUMP_BPL] = 0;
-
- if (!range_args(16 * MEMDUMP_BPL - 1)) // 16 Zeilen, wenn keine Endadresse angegeben
- return;
-
- do {
- FPrintf(fout, "%04lx:", address);
- for (i=0; i<MEMDUMP_BPL; i++, address++) {
- if (address == end_address) done = TRUE;
-
- FPrintf(fout, " %02lx", byte = SAMReadByte(address));
- if ((byte >= ' ') && (byte <= '~'))
- mem[i] = conv_from_64(byte);
- else
- mem[i] = '.';
- }
- FPrintf(fout, " '%s'\n", mem);
- } while (!done && !aborted());
- }
-
-
- /*
- * ASCII-Dump
- * i [start] [end]
- */
-
- #define ASCIIDUMP_BPL 64 // Bytes pro Zeile
-
- void ascii_dump(void)
- {
- BOOL done = FALSE;
- short i;
- UBYTE mem[ASCIIDUMP_BPL + 2];
- UBYTE byte;
-
- mem[ASCIIDUMP_BPL] = 0;
-
- if (!range_args(16 * ASCIIDUMP_BPL - 1)) // 16 Zeilen, wenn keine Endadresse angegeben
- return;
-
- do {
- FPrintf(fout, "%04lx:", address);
- for (i=0; i<ASCIIDUMP_BPL; i++, address++) {
- if (address == end_address) done = TRUE;
-
- byte = SAMReadByte(address);
- if ((byte >= ' ') && (byte <= '~'))
- mem[i] = conv_from_64(byte);
- else
- mem[i] = '.';
- }
- FPrintf(fout, " '%s'\n", mem);
- } while (!done && !aborted());
- }
-
-
- /*
- * Umwandlung PETSCII->ASCII
- */
-
- char conv_from_64(char c)
- {
- if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
- return c ^ 0x20;
- else
- return c;
- }
-
-
- /*
- * Screen-Code-Dump
- * n [start] [end]
- */
-
- #define SCRDUMP_BPL 64 // Bytes pro Zeile
-
- void screen_dump(void)
- {
- BOOL done = FALSE;
- short i;
- UBYTE mem[SCRDUMP_BPL + 2];
- UBYTE byte;
-
- mem[SCRDUMP_BPL] = 0;
-
- if (!range_args(16 * SCRDUMP_BPL - 1)) // 16 Zeilen, wenn keine Endadresse angegeben
- return;
-
- do {
- FPrintf(fout, "%04lx:", address);
- for (i=0; i<SCRDUMP_BPL; i++, address++) {
- if (address == end_address) done = TRUE;
-
- byte = SAMReadByte(address);
- if (byte < 90)
- mem[i] = conv_from_scode(byte);
- else
- mem[i] = '.';
- }
- FPrintf(fout, " '%s'\n", mem);
- } while (!done && !aborted());
- }
-
-
- /*
- * Umwandlung Bildschirmcode->ASCII
- */
-
- char conv_from_scode(char c)
- {
- c &= 0x7f;
-
- if (c <= 31)
- return c + 64;
- else
- if (c >= 64)
- return c + 32;
- else
- return c;
- }
-
-
- /*
- * Binär-Dump
- * b [start] [end]
- */
-
- void binary_dump(void)
- {
- BOOL done = FALSE;
- char bin[10];
-
- bin[8] = 0;
-
- if (!range_args(7)) // 8 Zeilen, wenn keine Endadresse angegeben
- return;
-
- do {
- if (address == end_address) done = TRUE;
-
- byte_to_bin(SAMReadByte(address), bin);
- FPrintf(fout, "%04lx: %s\n", address++, bin);
- } while (!done && !aborted());
- }
-
-
- /*
- * Sprite-Daten-Dump
- * p [start] [end]
- */
-
- void sprite_dump(void)
- {
- BOOL done = FALSE;
- short i;
- char bin[10];
-
- bin[8] = 0;
-
- if (!range_args(21 * 3 - 1)) // 21 Zeilen, wenn keine Endadresse angegeben
- return;
-
- do {
- FPrintf(fout, "%04lx: ", address);
- for (i=0; i<3; i++, address++) {
- if (address == end_address) done = TRUE;
-
- byte_to_bin(SAMReadByte(address), bin);
- FPrintf(fout, "%s", bin);
- }
- FPutC(fout, '\n');
- } while (!done && !aborted());
- }
-
-
- /*
- * Ein Byte in Binärfolge umwandeln
- */
-
- void byte_to_bin(UBYTE byte, char *str)
- {
- short i;
-
- for (i=0; i<8; i++, byte<<=1)
- if (byte & 0x80)
- str[i] = '#';
- else
- str[i] = '.';
- }
-
-
- /*
- * Disassemblieren
- * d [start] [end]
- */
-
- void disassemble(void)
- {
- BOOL done = FALSE;
- short i;
- UBYTE op[3];
- UWORD adr;
-
- if (!range_args(31)) // 32 Bytes, wenn keine Endadresse angegeben
- return;
-
- do {
- FPrintf(fout, "%04lx:", adr = address);
- for (i=0; i<3; i++, adr++) {
- if (adr == end_address) done = TRUE;
- op[i] = SAMReadByte(adr);
- }
- address += disass_line(address, op[0], op[1], op[2]);
- } while (!done && !aborted());
- }
-
-
- /*
- * Einen Befehl disassemblieren, Länge zurückgeben
- */
-
- int disass_line(UWORD adr, UBYTE op, UBYTE lo, UBYTE hi)
- {
- char mode = adr_mode[op], mnem = mnemonic[op];
-
- // Befehlsbytes hexadezimal ausgeben
- switch (adr_length[mode]) {
- case 1:
- FPrintf(fout, " %02lx ", op);
- break;
-
- case 2:
- FPrintf(fout, " %02lx %02lx ", op, lo);
- break;
-
- case 3:
- FPrintf(fout, " %02lx %02lx %02lx ", op, lo, hi);
- break;
- }
-
- // Undokumentierte Opcodes mit Stern markieren
- if (mnem > M_ILLEGAL)
- FPutC(fout, '*');
- else
- FPutC(fout, ' ');
-
- // Mnemonic ausgeben
- FPrintf(fout, "%lc%lc%lc ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem]);
-
- // Argument ausgeben
- switch (mode) {
- case A_IMPL:
- break;
-
- case A_ACCU:
- FPuts(fout, "a");
- break;
-
- case A_IMM:
- FPrintf(fout, "#%02lx", lo);
- break;
-
- case A_REL:
- FPrintf(fout, "%04lx", ((adr + 2) + (BYTE)lo) & 0xffff);
- break;
-
- case A_ZERO:
- FPrintf(fout, "%02lx", lo);
- break;
-
- case A_ZEROX:
- FPrintf(fout, "%02lx,x", lo);
- break;
-
- case A_ZEROY:
- FPrintf(fout, "%02lx,y", lo);
- break;
-
- case A_ABS:
- FPrintf(fout, "%04lx", (hi << 8) | lo);
- break;
-
- case A_ABSX:
- FPrintf(fout, "%04lx,x", (hi << 8) | lo);
- break;
-
- case A_ABSY:
- FPrintf(fout, "%04lx,y", (hi << 8) | lo);
- break;
-
- case A_IND:
- FPrintf(fout, "(%04lx)", (hi << 8) | lo);
- break;
-
- case A_INDX:
- FPrintf(fout, "(%02lx,x)", lo);
- break;
-
- case A_INDY:
- FPrintf(fout, "(%02lx),y", lo);
- break;
- }
-
- FPutC(fout, '\n');
- return adr_length[mode];
- }
-
-
- /*
- * Assemblieren
- * a [start]
- */
-
- void assemble(void)
- {
- BOOL done = FALSE;
- char c1, c2, c3;
- char mnem, mode;
- UBYTE opcode;
- UWORD arg;
- WORD rel;
-
- // Parameter lesen
- if (!address_args())
- return;
-
- do {
- FPrintf(fout, "%04lx> ", address);
- read_line();
-
- c1 = ToLower(get_char());
- c2 = ToLower(get_char());
- c3 = ToLower(get_char());
-
- if (c1 != '\n') {
-
- if ((mnem = find_mnemonic(c1, c2, c3)) != M_ILLEGAL) {
-
- get_token();
- if (instr_args(&arg, &mode)) {
-
- // Ggf. A_IMPL -> A_ACCU
- if ((mode == A_IMPL) && find_opcode(mnem, A_ACCU, &opcode))
- mode = A_ACCU;
-
- // Relative Adressierung getrennt behandeln
- if (((mode == A_ABS) || (mode == A_ZERO)) && find_opcode(mnem, A_REL, &opcode)) {
- mode = A_REL;
- rel = arg - (address + 2) & 0xffff;
- if ((rel < -128) || (rel > 127)) {
- error("Branch too long");
- continue;
- } else
- arg = rel & 0xff;
- }
-
- if (find_opcode(mnem, mode, &opcode)) {
-
- // Disassemblierte Zeile ausgeben
- FPrintf(fout, "\v%04lx:", address);
- disass_line(address, opcode, arg & 0xff, arg >> 8);
-
- switch (adr_length[mode]) {
- case 1:
- SAMWriteByte(address++, opcode);
- break;
-
- case 2:
- SAMWriteByte(address++, opcode);
- SAMWriteByte(address++, arg);
- break;
-
- case 3:
- SAMWriteByte(address++, opcode);
- SAMWriteByte(address++, arg & 0xff);
- SAMWriteByte(address++, arg >> 8);
- break;
-
- default:
- error("Internal error");
- break;
- }
-
- } else // Adressierungsart paßt nicht zum Befehl
- error("Addressing mode not supported by instruction");
-
- } else // Nicht erkannte Adressierungsart
- error("Unrecognized addressing mode");
-
- } else // Mnemonic nicht gefunden
- error("Unknown instruction");
-
- } else // Leerzeile beendet die Eingabe
- done = TRUE;
- } while (!done);
- }
-
-
- /*
- * Zu drei Buchstaben den passenden Mnemonic-Code finden
- * M_ILLEGAL: Kein passendes Mnemonic gefunden
- */
-
- char find_mnemonic(char op1, char op2, char op3)
- {
- int i;
- char c1, c2, c3;
-
- for (i=0; i<M_MAXIMUM; i++)
- if ((mnem_1[i] == op1) && (mnem_2[i] == op2) && (mnem_3[i] == op3))
- return i;
-
- return M_ILLEGAL;
- }
-
-
- /*
- * Opcode eines Befehls ermitteln, Mnemonic und Adressierungsart gegeben
- * TRUE: OK, FALSE: Mnemonic kommt mit dieser Adressierungsart nicht vor
- */
-
- BOOL find_opcode(char mnem, char mode, UBYTE *opcode)
- {
- int i;
-
- for (i=0; i<256; i++)
- if ((mnemonic[i] == mnem) && (adr_mode[i] == mode)) {
- *opcode = i;
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- /*
- * Speicherkonfiguration anzeigen/setzen
- * k [config]
- */
-
- void mem_config(void)
- {
- UWORD con;
-
- if (the_token != T_END)
- if (!expression(&con))
- return;
- else
- SAMMemConfig = con;
- else
- con = SAMMemConfig;
-
- FPrintf(fout, "Configuration: %ld\n", con & 7);
- FPrintf(fout, "A000-BFFF: %s\n", (con & 3) == 3 ? "Basic" : "RAM");
- FPrintf(fout, "D000-DFFF: %s\n", (con & 3) ? ((con & 4) ? "I/O" : "Char") : "RAM");
- FPrintf(fout, "E000-FFFF: %s\n", (con & 2) ? "Kernal" : "RAM");
- }
-
-
- /*
- * Füllen
- * k start end byte
- */
-
- void fill(void)
- {
- BOOL done = FALSE;
- UWORD adr, end_adr, value;
-
- if (!expression(&adr))
- return;
- if (!expression(&end_adr))
- return;
- if (!expression(&value))
- return;
-
- do {
- if (adr == end_adr) done = TRUE;
-
- SAMWriteByte(adr++, value);
- } while (!done);
- }
-
-
- /*
- * Vergleichen
- * c start end dest
- */
-
- void compare(void)
- {
- BOOL done = FALSE;
- UWORD adr, end_adr, dest;
- int num = 0;
-
- if (!expression(&adr))
- return;
- if (!expression(&end_adr))
- return;
- if (!expression(&dest))
- return;
-
- do {
- if (adr == end_adr) done = TRUE;
-
- if (SAMReadByte(adr) != SAMReadByte(dest)) {
- FPrintf(fout, "%04lx ", adr);
- num++;
- if (!(num & 7))
- FPutC(fout, '\n');
- }
- adr++; dest++;
- } while (!done && !aborted());
-
- if (num & 7)
- FPutC(fout, '\n');
- FPrintf(fout, "%ld byte(s) different\n", num);
- }
-
-
- /*
- * Kopieren
- * t start end dest
- */
-
- void transfer(void)
- {
- BOOL done = FALSE;
- UWORD adr, end_adr, dest;
-
- if (!expression(&adr))
- return;
- if (!expression(&end_adr))
- return;
- if (!expression(&dest))
- return;
-
- if (dest < adr)
- do {
- if (adr == end_adr) done = TRUE;
- SAMWriteByte(dest++,SAMReadByte(adr++));
- } while (!done);
- else {
- dest += end_adr - adr;
- do {
- if (adr == end_adr) done = TRUE;
- SAMWriteByte(dest--,SAMReadByte(end_adr--));
- } while (!done);
- }
- }
-
-
- /*
- * Speicher ändern
- * : addr {byte}
- */
-
- void modify(void)
- {
- UWORD adr, val;
-
- if (!expression(&adr))
- return;
-
- while (the_token != T_END)
- if (expression(&val))
- SAMWriteByte(adr++, val);
- else
- return;
- }
-
-
- /*
- * Ausdruck berechnen und anzeigen
- * ? expression
- */
-
- void print_expr(void)
- {
- UWORD val;
-
- if (!expression(&val))
- return;
-
- FPrintf(fout, "Hex: %04lx\nDec: %lu\n", val, val);
- }
-
-
- /*
- * Ausgabe umleiten
- * o [file]
- */
-
- void redir_output(void)
- {
- char c;
- char filename[INPUT_LENGTH];
- char *p = filename;
-
- // Alte Datei schließen
- if (fout != ferr) {
- Close(fout);
- fout = ferr;
- return;
- }
-
- // Leerzeichen überspringen
- while ((c = get_char()) == ' ') ;
-
- if (c == '\n')
- return;
-
- do {
- *p++ = c;
- } while ((c = get_char()) != '\n');
- *p++ = 0;
-
- if (!(fout = Open(filename, MODE_NEWFILE)))
- error("Unable to open file");
- }
-
-
- /*
- * Interrupt-Vektoren anzeigen
- */
-
- void int_vectors(void)
- {
- FPuts(fout, " IRQ BRK NMI\n");
- FPrintf(fout, "6510 : %04lx %04lx %04lx\n",
- SAMReadByte(0xffff) << 8 | SAMReadByte(0xfffe),
- SAMReadByte(0xffff) << 8 | SAMReadByte(0xfffe),
- SAMReadByte(0xfffb) << 8 | SAMReadByte(0xfffa));
-
- if (SAMMemConfig & 2)
- FPrintf(fout, "Kernal: %04lx %04lx %04lx\n",
- SAMReadByte(0x0315) << 8 | SAMReadByte(0x0314),
- SAMReadByte(0x0317) << 8 | SAMReadByte(0x0316),
- SAMReadByte(0x0319) << 8 | SAMReadByte(0x0318));
- }
-
-
- /*
- * Zustand der Customchips anzeigen
- */
-
- void view_state(void)
- {
- switch (get_char()) {
- case 'c': // CIA
- view_cia_state();
- break;
-
- case 's': // SID
- view_sid_state();
- break;
-
- case 'v': // VIC
- view_vic_state();
- break;
-
- default:
- error("Unknown command");
- break;
- }
- }
-
- void view_cia_state(void)
- {
- CIADump cd;
-
- switch (get_char()) {
- case '1':
- GetCIA1Dump(&cd);
- break;
- case '2':
- GetCIA2Dump(&cd);
- break;
- default:
- error("Unknown command");
- return;
- }
-
- FPrintf(fout, "Timer A : %s\n", cd.cra & 1 ? "On" : "Off");
- FPrintf(fout, " Counter : %04lx Latch: %04lx\n", (cd.ta_hi << 8) | cd.ta_lo, (cd.ltcha_hi << 8) | cd.ltcha_lo);
- FPrintf(fout, " Run mode: %s\n", cd.cra & 8 ? "One-shot" : "Continuous");
- FPrintf(fout, " Input : %s\n", cd.cra & 0x20 ? "CNT" : "ø2");
- FPuts(fout, " Output : ");
- if (cd.cra & 4)
- if (cd.cra & 8)
- FPuts(fout, "PB6 Toggle\n\n");
- else
- FPuts(fout, "PB6 Pulse\n\n");
- else
- FPuts(fout, "None\n\n");
-
- FPrintf(fout, "Timer B : %s\n", cd.crb & 1 ? "On" : "Off");
- FPrintf(fout, " Counter : %04lx Latch: %04lx\n", (cd.tb_hi << 8) | cd.tb_lo, (cd.ltchb_hi << 8) | cd.ltchb_lo);
- FPrintf(fout, " Run mode: %s\n", cd.crb & 8 ? "One-shot" : "Continuous");
- FPuts(fout, " Input : ");
- if (cd.crb & 0x40)
- if (cd.crb & 0x20)
- FPuts(fout, "Timer A underflow (CNT high)\n");
- else
- FPuts(fout, "Timer A underflow\n");
- else
- if (cd.crb & 0x20)
- FPuts(fout, "CNT\n");
- else
- FPuts(fout, "ø2\n");
- FPuts(fout, " Output : ");
- if (cd.crb & 4)
- if (cd.crb & 8)
- FPuts(fout, "PB7 Toggle\n\n");
- else
- FPuts(fout, "PB7 Pulse\n\n");
- else
- FPuts(fout, "None\n\n");
-
- FPrintf(fout, "TOD : %lx%lx:%lx%lx:%lx%lx.%lx %s\n",
- (cd.tod_hr >> 4) & 1, cd.tod_hr & 0x0f,
- (cd.tod_min >> 4) & 7, cd.tod_min & 0x0f,
- (cd.tod_sec >> 4) & 7, cd.tod_sec & 0x0f,
- cd.tod_10ths & 0x0f, cd.tod_hr & 0x80 ? "PM" : "AM");
- FPrintf(fout, "Alarm : %lx%lx:%lx%lx:%lx%lx.%lx %s\n",
- (cd.alm_hr >> 4) & 1, cd.alm_hr & 0x0f,
- (cd.alm_min >> 4) & 7, cd.alm_min & 0x0f,
- (cd.alm_sec >> 4) & 7, cd.alm_sec & 0x0f,
- cd.alm_10ths & 0x0f, cd.alm_hr & 0x80 ? "PM" : "AM");
- FPrintf(fout, "TOD input : %s\n", cd.cra & 0x80 ? "50Hz" : "60Hz");
- FPrintf(fout, "Write to : %s registers\n\n", cd.crb & 0x80 ? "Alarm" : "TOD");
-
- FPrintf(fout, "Serial data : %02lx\n", cd.sdr);
- FPrintf(fout, "Serial mode : %s\n\n", cd.cra & 0x40 ? "Output" : "Input");
-
- FPuts(fout, "Pending int.: ");
- dump_cia_ints(cd.int_data);
- FPuts(fout, "Enabled int.: ");
- dump_cia_ints(cd.int_mask);
- }
-
- void dump_cia_ints(UBYTE int)
- {
- if (int & 0x1f) {
- if (int & 1) FPuts(fout, "TA ");
- if (int & 2) FPuts(fout, "TB ");
- if (int & 4) FPuts(fout, "Alarm ");
- if (int & 8) FPuts(fout, "Serial ");
- if (int & 0x10) FPuts(fout, "Flag");
- } else
- FPuts(fout, "None");
- FPutC(fout, '\n');
- }
-
- void view_sid_state(void)
- {
- SIDDump sd;
-
- GetSIDDump(&sd);
-
- FPuts(fout, "Voice 1\n");
- FPrintf(fout, " Frequency : %04lx\n", (sd.freq_hi_1 << 8) | sd.freq_lo_1);
- FPrintf(fout, " Pulse Width: %04lx\n", ((sd.pw_hi_1 & 0x0f) << 8) | sd.pw_lo_1);
- FPrintf(fout, " Env. (ADSR): %lx %lx %lx %lx\n", sd.AD_1 >> 4, sd.AD_1 & 0x0f, sd.SR_1 >> 4, sd.SR_1 & 0x0f);
- FPuts(fout, " Waveform : ");
- dump_sid_waveform(sd.ctrl_1);
- FPrintf(fout, " Gate : %s Ring mod.: %s\n", sd.ctrl_1 & 0x01 ? "On " : "Off", sd.ctrl_1 & 0x04 ? "On" : "Off");
- FPrintf(fout, " Test bit : %s Synchron.: %s\n", sd.ctrl_1 & 0x08 ? "On " : "Off", sd.ctrl_1 & 0x02 ? "On" : "Off");
- FPrintf(fout, " Filter : %s\n", sd.res_filt & 0x01 ? "On" : "Off");
-
- FPuts(fout, "\nVoice 2\n");
- FPrintf(fout, " Frequency : %04lx\n", (sd.freq_hi_2 << 8) | sd.freq_lo_2);
- FPrintf(fout, " Pulse Width: %04lx\n", ((sd.pw_hi_2 & 0x0f) << 8) | sd.pw_lo_2);
- FPrintf(fout, " Env. (ADSR): %lx %lx %lx %lx\n", sd.AD_2 >> 4, sd.AD_2 & 0x0f, sd.SR_2 >> 4, sd.SR_2 & 0x0f);
- FPuts(fout, " Waveform : ");
- dump_sid_waveform(sd.ctrl_2);
- FPrintf(fout, " Gate : %s Ring mod.: %s\n", sd.ctrl_2 & 0x01 ? "On " : "Off", sd.ctrl_2 & 0x04 ? "On" : "Off");
- FPrintf(fout, " Test bit : %s Synchron.: %s\n", sd.ctrl_2 & 0x08 ? "On " : "Off", sd.ctrl_2 & 0x02 ? "On" : "Off");
- FPrintf(fout, " Filter : %s\n", sd.res_filt & 0x02 ? "On" : "Off");
-
- FPuts(fout, "\nVoice 3\n");
- FPrintf(fout, " Frequency : %04lx\n", (sd.freq_hi_3 << 8) | sd.freq_lo_3);
- FPrintf(fout, " Pulse Width: %04lx\n", ((sd.pw_hi_3 & 0x0f) << 8) | sd.pw_lo_3);
- FPrintf(fout, " Env. (ADSR): %lx %lx %lx %lx\n", sd.AD_3 >> 4, sd.AD_3 & 0x0f, sd.SR_3 >> 4, sd.SR_3 & 0x0f);
- FPuts(fout, " Waveform : ");
- dump_sid_waveform(sd.ctrl_3);
- FPrintf(fout, " Gate : %s Ring mod.: %s\n", sd.ctrl_3 & 0x01 ? "On " : "Off", sd.ctrl_3 & 0x04 ? "On" : "Off");
- FPrintf(fout, " Test bit : %s Synchron.: %s\n", sd.ctrl_3 & 0x08 ? "On " : "Off", sd.ctrl_3 & 0x02 ? "On" : "Off");
- FPrintf(fout, " Filter : %s Mute : %s\n", sd.res_filt & 0x04 ? "On" : "Off", sd.mode_vol & 0x80 ? "Yes" : "No");
-
- FPuts(fout, "\nFilters/Volume\n");
- FPrintf(fout, " Frequency: %04lx\n", (sd.fc_hi << 3) | (sd.fc_lo & 0x07));
- FPrintf(fout, " Resonance: %lx\n", sd.res_filt >> 4);
- FPuts(fout, " Mode : ");
- if (sd.mode_vol & 0x70) {
- if (sd.mode_vol & 0x10) FPuts(fout, "Low-pass ");
- if (sd.mode_vol & 0x20) FPuts(fout, "Band-pass ");
- if (sd.mode_vol & 0x40) FPuts(fout, "High-pass");
- } else
- FPuts(fout, "None");
- FPrintf(fout, "\n Volume : %lx\n", sd.mode_vol & 0x0f);
- }
-
- void dump_sid_waveform(UBYTE wave)
- {
- if (wave & 0xf0) {
- if (wave & 0x10) FPuts(fout, "Triangle ");
- if (wave & 0x20) FPuts(fout, "Sawtooth ");
- if (wave & 0x40) FPuts(fout, "Rectangle ");
- if (wave & 0x80) FPuts(fout, "Noise");
- } else
- FPuts(fout, "None");
- FPutC(fout, '\n');
- }
-
- void view_vic_state(void)
- {
- VICDump vd;
- short i;
-
- GetVICDump(&vd);
-
- FPrintf(fout, "Raster line : %04lx\n", vd.raster | ((vd.ctrl1 & 0x80) << 1));
- FPrintf(fout, "IRQ raster line : %04lx\n\n", vd.irq_raster);
-
- FPrintf(fout, "X scroll : %ld\n", vd.ctrl2 & 7);
- FPrintf(fout, "Y scroll : %ld\n", vd.ctrl1 & 7);
- FPrintf(fout, "Horizontal border : %ld columns\n", vd.ctrl2 & 8 ? 40 : 38);
- FPrintf(fout, "Vertical border : %ld rows\n\n", vd.ctrl1 & 8 ? 25 : 24);
-
- FPuts(fout, "Display mode : ");
- switch (((vd.ctrl1 >> 5) & 3) | ((vd.ctrl2 >> 2) & 4)) {
- case 0:
- FPuts(fout, "Standard text\n");
- break;
- case 1:
- FPuts(fout, "Multicolor text\n");
- break;
- case 2:
- FPuts(fout, "Standard bitmap\n");
- break;
- case 3:
- FPuts(fout, "Multicolor bitmap\n");
- break;
- case 4:
- FPuts(fout, "ECM text\n");
- break;
- case 5:
- FPuts(fout, "Invalid text (ECM+MCM)\n");
- break;
- case 6:
- FPuts(fout, "Invalid bitmap (ECM+BMM)\n");
- break;
- case 7:
- FPuts(fout, "Invalid bitmap (ECM+BMM+ECM)\n");
- break;
- }
- FPrintf(fout, "Sequencer state : %s\n", vd.idle_state ? "Idle" : "Display");
- FPrintf(fout, "Bad line state : %s\n", vd.bad_line ? "Yes" : "No");
- FPrintf(fout, "Bad lines enabled : %s\n", vd.bad_line_enable ? "Yes" : "No");
- FPrintf(fout, "Video counter : %04lx\n", vd.vc);
- FPrintf(fout, "Video counter base: %04lx\n", vd.vcbase);
- FPrintf(fout, "Row counter : %ld\n\n", vd.rc);
-
- FPrintf(fout, "VIC bank : %04lx-%04lx\n", vd.bank_base, vd.bank_base + 0x3fff);
- FPrintf(fout, "Video matrix base : %04lx\n", vd.matrix_base);
- FPrintf(fout, "Character base : %04lx\n", vd.char_base);
- FPrintf(fout, "Bitmap base : %04lx\n\n", vd.bitmap_base);
-
- FPrintf(fout, " Spr.0 Spr.1 Spr.2 Spr.3 Spr.4 Spr.5 Spr.6 Spr.7\n");
- FPuts(fout, "Enabled: "); dump_spr_flags(vd.me);
- FPrintf(fout, "Data : %04lx %04lx %04lx %04lx %04lx %04lx %04lx %04lx\n",
- vd.sprite_base[0], vd.sprite_base[1], vd.sprite_base[2], vd.sprite_base[3],
- vd.sprite_base[4], vd.sprite_base[5], vd.sprite_base[6], vd.sprite_base[7]);
- FPrintf(fout, "MC : %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx\n",
- vd.mc[0], vd.mc[1], vd.mc[2], vd.mc[3], vd.mc[4], vd.mc[5], vd.mc[6], vd.mc[7]);
-
- FPuts(fout, "Mode : ");
- for (i=0; i<8; i++)
- if (vd.mmc & (1<<i))
- FPuts(fout, "Multi ");
- else
- FPuts(fout, "Std. ");
-
- FPuts(fout, "\nX-Exp. : "); dump_spr_flags(vd.mxe);
- FPuts(fout, "Y-Exp. : "); dump_spr_flags(vd.mye);
-
- FPuts(fout, "Prio. : ");
- for (i=0; i<8; i++)
- if (vd.mdp & (1<<i))
- FPuts(fout, "Back ");
- else
- FPuts(fout, "Fore ");
-
- FPuts(fout, "\n\nPending interrupts: ");
- dump_vic_ints(vd.irq_flag);
- FPuts(fout, "Enabled interrupts: ");
- dump_vic_ints(vd.irq_mask);
- }
-
- void dump_spr_flags(UBYTE f)
- {
- short i;
-
- for (i=0; i<8; i++)
- if (f & (1<<i))
- FPuts(fout, "Yes ");
- else
- FPuts(fout, "No ");
-
- FPutC(fout, '\n');
- }
-
- void dump_vic_ints(UBYTE int)
- {
- if (int & 0x1f) {
- if (int & 1) FPuts(fout, "Raster ");
- if (int & 2) FPuts(fout, "Spr-Data ");
- if (int & 4) FPuts(fout, "Spr-Spr ");
- if (int & 8) FPuts(fout, "Lightpen");
- } else
- FPuts(fout, "None");
- FPutC(fout, '\n');
- }
-